package com.light.fileserver.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QRUtil {

	/**
	 * 编码（将文本生成二维码）
	 * 
	 * @param content   二维码中的内容
	 * @param width     二维码图片宽度
	 * @param height    二维码图片高度
	 * @param imagePath 二维码图片存放位置
	 * @return 图片地址
	 */
	public static String encode(String content, int width, int height, String imagePath) {

		Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
		// 设置编码类型为utf-8
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		// 设置二维码纠错能力级别为Q
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);

		BitMatrix byteMatrix = null;
		try {
			// 生成二维码
			byteMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			File file = new File(imagePath);
			MatrixToImageWriter.writeToPath(byteMatrix, "png", file.toPath());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (WriterException e) {
			e.printStackTrace();
		}
		return imagePath;
	}

	/**
	 * 解码（读取二维码图片中的文本信息）
	 * 
	 * @param imagePath 二维码图片路径
	 * @return 文本信息
	 */
	public static String decode(String imagePath) {
		// 返回的文本信息
		String content = "";
		try {
			// 创建图片文件
			File file = new File(imagePath);
			if (!file.exists()) {
				return content;
			}
			BufferedImage image = null;
			image = ImageIO.read(file);
			if (null == image) {
				return content;
			}
			// 解码
			LuminanceSource source = new BufferedImageLuminanceSource(image);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
			Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
			hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
			Result rs = new MultiFormatReader().decode(bitmap, hints);
			content = rs.getText();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ReaderException e) {
			e.printStackTrace();
		}
		return content;
	}

	/**
	 * 图片打水印
	 * 
	 * @param bgImage    背景图
	 * @param waterImg   水印图
	 * @param uniqueFlag 生成的新图片名称中的唯一标识，用来保证生成的图片名称不重复，如果为空或为null,将使用当前时间作为标识
	 * @return 新图片路径
	 */
	public static String addImageWater(String bgImage, String waterImg, String uniqueFlag) {

		int x = 0;
		int y = 0;
		String newImgPath = "";

		if (null == uniqueFlag) {
			uniqueFlag = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		} else if (uniqueFlag.trim().length() < 1) {
			uniqueFlag = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		}

		try {
			File file = new File(bgImage);
			String fileName = file.getName();
			Image image = ImageIO.read(file);
			int width = image.getWidth(null);
			int height = image.getHeight(null);
			BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = bufferedImage.createGraphics();
			g.drawImage(image, 0, 0, width, height, null);

			Image waterImage = ImageIO.read(new File(waterImg)); // 水印文件
			int width_water = waterImage.getWidth(null);
			int height_water = waterImage.getHeight(null);
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));

			int widthDiff = width - width_water;
			int heightDiff = height - height_water;

			x = widthDiff / 2;
			y = heightDiff / 2;

			g.drawImage(waterImage, x, y, width_water, height_water, null); // 水印文件结束
			g.dispose();

			if (bgImage.contains(fileName)) {
				newImgPath = bgImage.replace(fileName, uniqueFlag + fileName);
			}
			File newImg = new File(newImgPath);
			ImageIO.write(bufferedImage, "png", newImg);

			File waterFile = new File(waterImg);

			if (file.exists()) {
				file.delete();
			}

			if (waterFile.exists()) {
				waterFile.delete();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return newImgPath;
	}

	/**
	 * 图片缩放
	 * 
	 * @param filePath 图片路径
	 * @param height   缩放到高度
	 * @param width    缩放宽度
	 * @param fill     比例足时是否填白 true为填白，二维码是黑白色，这里调用时建议设为true
	 * @return 新图片路径
	 */
	public static String resizeImg(String filePath, int width, int height, boolean fill) {

		String newImgPath = "";

		try {
			double ratio = 0; // 缩放比例
			File f = new File(filePath);
			String fileName = f.getName();
			BufferedImage bi = ImageIO.read(f);
			Image itemp = bi.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);

			if (height != 0 && width != 0) {
				// 计算比例
				if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
					if (bi.getHeight() > bi.getWidth()) {
						ratio = (new Integer(height)).doubleValue() / bi.getHeight();
					} else {
						ratio = (new Integer(width)).doubleValue() / bi.getWidth();
					}
					AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
					itemp = op.filter(bi, null);
				}
			}

			if (fill) {
				BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
				Graphics2D g = image.createGraphics();
				g.setColor(Color.white);
				g.fillRect(0, 0, width, height);
				if (width == itemp.getWidth(null)) {
					g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2, itemp.getWidth(null),
							itemp.getHeight(null), Color.white, null);
				} else {
					g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null),
							itemp.getHeight(null), Color.white, null);
				}

				g.dispose();
				itemp = image;
			}
			String now = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
			if (filePath.contains(fileName)) {
				newImgPath = filePath.replace(fileName, now + fileName);
			}

			File newImg = new File(newImgPath);
			ImageIO.write((BufferedImage) itemp, "png", newImg);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return newImgPath;
	}

	/**
	 * 图片添加边框
	 * 
	 * @param mainImgPath 要加边框的图片
	 * @param bgImgPath   背景图（实际上是将图片放在背景图上，只利用背景图的边框效果）
	 * @return 制作完成的图片路径
	 */
	public static String addWaterBorder(String mainImgPath, String bgImgPath) {

		String borderImgPath = "";

		try {
			File f = new File(mainImgPath);

			BufferedImage bi;

			bi = ImageIO.read(f);

			// 背景图长宽都比主图多4像素，这是因为我画的背景图的边框效果的大小正好是4像素，
			// 主图周边比背景图少4像素正好能把背景图的边框效果完美显示出来
			int width = bi.getWidth();
			int height = bi.getHeight();

			int bgWidth = width + 4;
			int bgHeight = height + 4;

			String now = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
			borderImgPath = QRUtil.addImageWater(QRUtil.resizeImg(bgImgPath, bgHeight, bgWidth, true), mainImgPath,
					now);

			if (f.exists()) {
				f.delete();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return borderImgPath;
	}

	public static void main(String[] args) {

		/** 部分一开始***********生成常规二维码 *************/
		// 二维码内容
		//String content = "介个是内容，http://weibo.com/sdtvwp";
		// 二维码宽度
		//int width = 300;
		// 二维码高度
		//int height = 300;
		// 二维码存放地址
		//String imagePath = "/tmp/qr/thatway_weibo.png";
		// 生成二维码,返回的是生成好的二维码图片的所在路径
		//String qrImgPath = QRUtil.encode(content, width, height, imagePath);
		/** 部分一结束***********如果生成不带图片的二维码，到这步已经完成了 *************/

		/** 部分二开始***********如果生成带图片但图片不带边框的二维码，解开这部分注释 *************/

		// 缩放水印图片,为保证二维码的读取正确，图片不超过二维码图片的五分之一，这里设为六分之一
		//String waterImgPath = QRUtil.resizeImg("/tmp/qr/heihei.png", width/6, height/6, true);
		//生成带有图片的二维码，返回的是生成好的二维码图片的所在路径
		//String qrImage = QRUtil.addImageWater(qrImgPath, waterImgPath,"thatway");
		/** 部分二结束***********如果生成带图片但图片不带边框的二维码，解开这部分注释 *************/

		/** 部分三开始（部分三不能和部分二共存）***********如果生成带图片且图片带边框的二维码，解开这部分注释 ****/

		// 缩放水印图片,为保证二维码的读取正确，图片不超过二维码图片的五分之一，这里设为六分之一
		// d:/qr/heihei.png 这图片是要加在二维码中间的那张图
		//String waterImgPath = QRUtil.resizeImg("d:/qr/heihei.png", width / 6, height / 6, true);

		// d:/qr/qr_bg.png这种图片是自己画好边框光晕效果的边框底图
		//String tempImg = QRUtil.addWaterBorder(waterImgPath, "d:/qr/qr_bg.png");

		// 生成带有边框图片的二维码,返回的是生成好的二维码图片的所在路径
		//String qrImage = QRUtil.addImageWater(qrImgPath, tempImg, "thatway");
		/** 部分三结束***********如果生成带图片且图片带边框的二维码，解开这部分注释 *************/

		/******* 测试一下解码 ******/
		System.out.println(QRUtil.decode("/tmp/qr/qrcode_develong_1.jpg"));
	}
}
